package sy5_Structural_Pattern.decorator;
/*
 * 装饰模式包括抽象构件Component、具体构件ConcreteComponent、抽象装饰类Decorator和具体装饰类ConcreteDecorator共四个角色
 * ConcreteComponent表示被装饰对象
 * Component是ConcreteComponent和Decorator的共同父类
 * 子类Decorator聚合了父类Component
 * 要点：通过调用Decorator对象，动态地给ConcreteComponent对象添加新的功能。
 */

abstract class Component{  //角色1：抽象构件，也可设计为接口
	protected  abstract String  operation(); //抽象方法
}

class ConcreteComponent extends Component{  //角色2：具体构件（被装饰类）
	@Override
	public String operation() {
		return "我学习过的编程语言有：C语言";
	}  
}

abstract class Decorator extends Component{  //角色3：抽象装饰类（核心类）
	
	private Component component; //维护一个抽象构件（父类）对象
	
	public Decorator(Component component) { //聚合（构造器注入）
		this.component = component;
	}

	public Component getComponent() {
		return component;
	}
	//抽象类Decorator作为抽象类Component的子类，可以不重写父类的抽象方法，而是延迟到具体类！
}

class ConcreteDecoratorA extends Decorator{  //角色4：具体装饰类
	public ConcreteDecoratorA(Component component) {
		super(component);  //调用父类构造方法
	}

	@Override
	public String operation() {  //接口方法在具体装饰类里实现
		//每个具体装饰类都可使用Component类型的对象，因而可调用operation()
		return getComponent().operation()+",C++";  //字符串相加，体现装饰
	}
}

class ConcreteDecoratorB extends Decorator{  //角色4：具体装饰类
	public ConcreteDecoratorB(Component component) {
		super(component);  //调用父类构造方法
	}
	@Override
	public String operation() {
		return getComponent().operation()+",Java";  //字符串相加，体现装饰
	}
}

public class Client {  //客户端测试类
	public static void main(String[] args) {
		Component component = new ConcreteComponent();  //无参构造方法
		System.out.println("大一，"+component.operation());
		System.out.println("================================");
		
		Decorator concreteDecoratorA = new ConcreteDecoratorA(component);  //有参构造方法
		System.out.println("大二，"+concreteDecoratorA.operation());
		System.out.println("===================================");
		
		Decorator concreteDecoratorB = new ConcreteDecoratorB(concreteDecoratorA);  //有参构造方法
		System.out.println("大三，"+concreteDecoratorB.operation());
		System.out.println("========================================");
	}
}
